import { View } from '@tarojs/components'
import { forwardRef, memo, useImperativeHandle, useRef, ReactNode, useMemo } from 'react'
import BtForm from '@/BtComponents/BtForm'
import { formContextProvider } from '@/BtComponents/BtForm/formContextProvider'
import BtFormItem from '../BtFormItem'
import BtInput from '../BtInput'
import BtPicker from '../BtPicker'
import BtUpload from '../BtUpload'
import './index.scss'

// 表单项类型
export enum FormItemType {
  INPUT = 'input',
  TEXTAREA = 'textarea',
  PICKER = 'picker',
  UPLOAD = 'upload',
  SWITCH = 'switch',
  CUSTOM = 'custom',
  CLASSIFY = 'classify'
}

// 基础表单项配置
interface BaseFormItemConfig {
  type: FormItemType
  label: string
  placeholder?: string
  maxLength?: number
  required?: boolean
  iconRemark?: string
  haveUnderline?: boolean
  selector?: any[]
  children?: Omit<FormItemConfig, 'label'| 'children'>[]
  show?: boolean
  render?: (props: {
    value: any
    onChange: (value: any) => void
  }) => ReactNode
  onChange?: (value: any, model: Record<string, any>) => void
}

// 分类标题配置
interface ClassifyFormItemConfig extends BaseFormItemConfig {
  type: FormItemType.CLASSIFY
  prop?: string
  enableProp?: never
}

// 普通表单项配置
interface NormalFormItemConfig extends BaseFormItemConfig {
  type: Exclude<FormItemType, FormItemType.CLASSIFY>
  enableProp?: never
  prop: string
}

// 可配置表单项配置
interface ConfigurableFormItemConfig extends BaseFormItemConfig {
  type: Exclude<FormItemType, FormItemType.CLASSIFY>
  enableProp: string
  prop?: string
}

// 联合类型
export type FormItemConfig = ClassifyFormItemConfig | NormalFormItemConfig | ConfigurableFormItemConfig

interface BtCustomFormProps {
  config: FormItemConfig[]
  model: Record<string, any>
  onChange: (value: any, key: string) => void
  className?: string
  rules?: any
}

// 控件配置类型（不包含label和children）
type FormControlConfig = Omit<NormalFormItemConfig | ConfigurableFormItemConfig, 'label' | 'children'>

function BtCustomForm({
  config,
  model,
  onChange,
  className = '',
  rules = {}
}: BtCustomFormProps, ref) {
  const fromRef = useRef<any>(null)

  // 处理配置项，最后一项设置 haveUnderline: false 不需要下划线
  const processedConfig = useMemo(() => {
    const result: FormItemConfig[] = []
    config.forEach((item, index) => {
      if (index === config.length -1 || (config[index + 1] && config[index + 1].type === FormItemType.CLASSIFY)) {
        // 处理上一组的最后一项
        item.haveUnderline = false
      }
      result.push({ ...item })
    })
    return result
  }, [config])

  const validate = () => {
    return fromRef.current.validate()
  }

  useImperativeHandle(ref, () => ({
    validate
  }))

  // 处理值变化
  const handleChange = (value: any, key: string, item: FormControlConfig) => {
    // 先调用项目自身的 onChange
    if (item.onChange) {
      item.onChange(value, model)
    }
    // 再调用表单的 onChange
    onChange(value, key)
  }

  // 渲染表单控件
  const renderFormControl = (item: FormControlConfig) => {
    const { type, prop, placeholder, maxLength, selector, render } = item

    if (!prop) return null

    if (render) {
      return render({
        value: model[prop],
        onChange: (value) => handleChange(value, prop, item)
      })
    }

    switch (type) {
      case FormItemType.INPUT:
        return (
          <BtInput
            value={model[prop]}
            placeholder={placeholder}
            maxLength={maxLength}
            onChange={value => handleChange(value, prop, item)}
            prop={prop}
          />
        )

      case FormItemType.TEXTAREA:
        return (
          <BtInput
            type='textarea'
            value={model[prop]}
            placeholder={placeholder}
            maxLength={maxLength}
            onChange={value => handleChange(value, prop, item)}
            prop={prop}
          />
        )

      case FormItemType.PICKER:
        return (
          selector && <BtPicker
            value={model[prop]}
            selector={selector}
            onChange={e => handleChange(e.detail.value, prop, item)}
            prop={prop}
          />
        )

      case FormItemType.UPLOAD:
        return (
          <BtUpload
            prop={prop}
            value={model[prop]}
            onChange={value => handleChange(value, prop, item)}
          />
        )

      case FormItemType.CUSTOM:
        return null

      default:
        return null
    }
  }

  // 渲染表单项
  const renderFormItem = (item: FormItemConfig) => {
    const { label, prop, enableProp, iconRemark, haveUnderline, children } = item

    // 分类标题直接返回
    if (item.type === FormItemType.CLASSIFY) {
      return (
        <View className='bt-custom-form__classify' key={label}>
          {label}
        </View>
      )
    }

    return (
      <View key={prop || enableProp} className='bt-custom-form__item'>
        <BtFormItem
          label={label}
          prop={prop}
          enable={enableProp ? model[enableProp] : undefined}
          iconRemark={iconRemark}
          haveUnderline={haveUnderline}
          onChange={e => handleChange(e.detail.value, enableProp || '', item as FormControlConfig)}
        >
          {enableProp !== undefined ? (
            <>
              {(!enableProp || model[enableProp]) && children?.map((child, index) => (
                <View key={index}>
                  {renderFormControl(child as FormControlConfig)}
                </View>
              ))}
            </>
          ) : (
            renderFormControl(item as FormControlConfig)
          )}
        </BtFormItem>
      </View>
    )
  }

  return (
    <View className={`bt-custom-form ${className}`}>
      <formContextProvider.Provider>
        <BtForm ref={fromRef} config={config} model={model} rules={rules}>
          {processedConfig
            .filter(item => item.show === true || item.show === undefined)
            .map(item => renderFormItem(item))
          }
        </BtForm>
      </formContextProvider.Provider>
    </View>
  )
}

const ChildFun = forwardRef(BtCustomForm)

export default memo(ChildFun)
